import { ElMessage } from 'element-plus';
import { UploadUserFile } from 'element-plus/es/components/upload/src/upload';
import { defineStore } from 'pinia';

import {
  BaseFeatureSetReq,
  getFileId,
  getPresignedUrls,
  getUploadId,
  getUploadList,
  importFile,
  mergeChunks,
  updateErrorStatus,
  updateImporting,
  updateItemStatus,
  updateStatus,
} from 'src/api/featureSet';
import { authedApi } from 'src/utils/axios';
import {
  OnFileProgress,
  PlatformUploadLoading,
  createFileChunk,
  usePlatformUploadStore,
} from 'stores/platform-upload';

export interface CurrentFeatureSet {
  feature_set_id: string;
  project_id: string;
}
export interface ActionFeatureSetReq extends BaseFeatureSetReq {
  action: string;
}
export const uploadErrorQueueItem = (req: ActionFeatureSetReq) => {
  return updateErrorStatus(req);
};

/* 创建切片进度条 */

const platformUploadStore = usePlatformUploadStore();

/*
 * 请求优先级：
 * upload: 0 最高
 * success_upload: 1
 * merge: 2
 * import: 3
 * success: 4
 * fetch_dataset: 5
 * clean: 999
 *
 * */
export const usePlatformFeatureSetUploadStore = defineStore(
  'platformFeatureUploadStore',
  {
    state: () => ({
      platformMaxFileSize: 2 * 1024 * 1024 * 1024,
      platformChunkSize: 10 * 1024 * 1024,
      platformUploadCount: 0,
      platformCurrentProcessId: [] as string[],
      platformCurrentUploadId: '' as string,
      platformPermitScheduler: false,
      platformUploadModalShow: false,
      platformFeatureSetStatusChange: false,
      platformCurrentUploadFeatureSet: {} as {
        feature_set_id: string;
        project_id: string;
      },
      platformJumpRequestId: [] as string[],
      platformFailureFeatureSetId: [] as string[],
      platformMaxUploadRequestNum: 1,
      platformRequestChunkSignal: false,
      platformRequestSignal: false,
      platformUploadUrlsMapper: {} as Record<string, Record<string, string[]>>,
      platformUploadIdMapper: {} as Record<string, Record<string, string>>,
      platformUploadQueue: [] as platformUploadQueue[],
      platformUploadFileList: {} as Record<string, PlatformUploadUserFile[]>,
      platformUploadList: [] as UploadFeatureSetList[],
      platformFeatureSetFileContainer: {} as Record<string, FileContainer>,
      platformUploadLoading: {
        beforeStartUploading: false,
      } as PlatformUploadLoading,
      vueUploadComponentFileList: [] as UploadUserFile[],
      reUploadList: [] as UploadFeatureSetList[],
      platformDeleteFeatureSetId: [] as number[],
    }),
    actions: {
      setReUploadList(lists: UploadFeatureSetList[]) {
        this.reUploadList = lists;
      },
      setCurUploadFeatureSet(featureSet: CurrentFeatureSet) {
        this.platformCurrentUploadFeatureSet = {
          feature_set_id: featureSet.feature_set_id,
          project_id: featureSet.project_id,
        };
      },

      excludeDelId(id: number) {
        this.platformDeleteFeatureSetId =
          this.platformDeleteFeatureSetId.filter((_id) => _id != id);
      },

      excludeErrorId(id: string) {
        this.platformFailureFeatureSetId =
          this.platformFailureFeatureSetId.filter((id_) => id_ != id);
        this.platformCurrentProcessId = this.platformCurrentProcessId.filter(
          (id_) => id_ != id
        );
      },

      setCurProcessDatasetIds(id: string[]) {
        this.platformCurrentProcessId = id;
      },
      pushFileList(uploadFile: UploadUserFile) {
        this.vueUploadComponentFileList.push(uploadFile);
      },

      setCurProcessFeatureSetId(id: string) {
        this.platformCurrentProcessId.push(id);
        this.platformCurrentUploadId = id;
      },

      setFileList(uploadFile: UploadUserFile) {
        this.vueUploadComponentFileList = [uploadFile];
      },
      pushUploadQueue(queueItem: platformUploadQueue) {
        this.platformUploadQueue.push(queueItem);
      },
      openUploadModal() {
        platformUploadStore.platformUploadModalShow = true;
        platformUploadStore.platformCurType = 'featureSet';
      },
      closeUploadModal() {
        this.platformUploadModalShow = false;
      },

      async prepareUploadUrls(featureSet: CurrentFeatureSet) {
        const { feature_set_id, project_id } = featureSet;
        const count = this.platformUploadFileList[feature_set_id].length;
        let index = 0;

        return new Promise((resolve, reject) => {
          this.platformUploadFileList[feature_set_id].map(async (item) => {
            try {
              const presignedUrlsResponse = await getPresignedUrls({
                feature_set_id,
                upload_id:
                  this.platformUploadIdMapper[feature_set_id][item.name],
                project_id,
              });
              const urls = presignedUrlsResponse.data.urls;
              this.platformUploadUrlsMapper[feature_set_id] =
                this.platformUploadUrlsMapper[feature_set_id] || {};
              this.platformUploadUrlsMapper[feature_set_id][item.name] = urls;
              index++;

              if (count == index) {
                resolve('success');
              }
            } catch (e) {
              console.log(e, 'e');
              return reject('init fail');
            }
          });
        });
      },

      async startUploadPrepare(featureSet: CurrentFeatureSet) {
        const { feature_set_id } = featureSet;
        await this.refreshFeatureSetList();
        try {
          await this.prepareFileUploadId(featureSet);
          await this.prepareUploadUrls(featureSet);
          this.setCurUploadFeatureSet(featureSet);
          this.setCurProcessFeatureSetId(feature_set_id);
          this.platformUploadLoading.beforeStartUploading = false;
        } catch (err) {
          console.log(err, 'err');
          this.platformUploadLoading.beforeStartUploading = false;
          ElMessage.error('任务初始化失败,请继续创建数据集');
          this.platformDeleteFeatureSetId.push(Number(feature_set_id));
          location.reload();
          return;
        }
      },

      async startUploadStart(featureSet: CurrentFeatureSet) {
        const { feature_set_id } = featureSet;
        this.openUploadModal();
        await this.prepareUploadChunks(String(feature_set_id));
        await this.startUpload(featureSet);
      },

      async prepareUploadChunks(feature_set_id: string) {
        const fileRow = this.platformUploadFileList[feature_set_id];
        this.platformFeatureSetFileContainer[feature_set_id] = this
          .platformFeatureSetFileContainer[feature_set_id] || {
          fileChunks: {},
          fileNoChunks: {},
        };
        if (!fileRow.length) return;
        let filename;
        for (const rowFile of fileRow) {
          filename = rowFile.name;
          if (rowFile.raw && rowFile.raw.size <= this.platformChunkSize) {
            this.platformFeatureSetFileContainer[feature_set_id].fileNoChunks[
              filename
            ] = [
              {
                file: rowFile.raw,
                size: rowFile.raw.size,
                percentage: 0,
                filename: rowFile.name,
              },
            ];
          } else {
            const fileChunkList = createFileChunk(
              rowFile.raw!,
              this.platformChunkSize
            );
            this.platformFeatureSetFileContainer[feature_set_id].fileChunks[
              filename
            ] = fileChunkList.map(({ file }, index) => ({
              chunk: file,
              hash: rowFile.name + '-' + index,
              index: index,
              filename: rowFile.name,
              percentage: 0,
              size: file.size,
              rowName: rowFile.name,
              rowSize: rowFile.size!,
            }));
          }
        }
      },
      async initPlatformUploadList() {
        const uploadListResponse = await getUploadList();
        this.platformUploadList = uploadListResponse.data;
      },

      async refreshFeatureSetList() {
        this.platformFeatureSetStatusChange =
          !this.platformFeatureSetStatusChange;
      },

      async prepareFileUploadId(featureSet: CurrentFeatureSet) {
        const { feature_set_id, project_id } = featureSet;
        this.clearVueUploadComponentFileList(feature_set_id);
        const count = this.platformUploadFileList[feature_set_id].length;
        let index = 0;
        return new Promise((resolve, reject) => {
          this.platformUploadFileList[feature_set_id].map(async (item) => {
            try {
              const uploadIdResponse = await getUploadId({
                feature_set_id: feature_set_id,
                total_size: item.size!,
                row_name: item.name,
                chunk_size: platformUploadStore.platformChunkSize,
                identifier: `${feature_set_id}_${project_id}_${item.name}`,
                project_id,
              });
              this.platformUploadIdMapper[feature_set_id] =
                this.platformUploadIdMapper[feature_set_id] || {};
              this.platformUploadIdMapper[feature_set_id][item.name] =
                uploadIdResponse.data.upload_id;
              index++;

              if (index == count) {
                await this.initPlatformUploadList();
                resolve('success');
              }
            } catch (e) {
              location.reload();
              this.forceClean(String(featureSet));
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshFeatureSetList(),
              ]);
            }
          });
        });
      },
      setVueUploadComponentFileListEmpty() {
        this.vueUploadComponentFileList = [];
      },
      clearVueUploadComponentFileList(id: string) {
        this.platformUploadFileList[id] = [
          ...(this.vueUploadComponentFileList as PlatformUploadUserFile[]),
        ];
        this.platformUploadFileList[id].forEach((uploadListItem) => {
          uploadListItem.feature_set_id = id;
        });
        this.vueUploadComponentFileList = [];
      },
      async startUpload(
        featureSet: CurrentFeatureSet,
        uploaded?: Record<string, Record<string, string[]>>
      ) {
        const chunkKeys = Object.keys(
          this.platformFeatureSetFileContainer[featureSet.feature_set_id]
            .fileChunks
        );

        const noChunkKeys = Object.keys(
          this.platformFeatureSetFileContainer[featureSet.feature_set_id]
            .fileNoChunks
        );

        if (!chunkKeys.length && !noChunkKeys.length) return;

        const formDataNoChunks: FormDataNoChunks[] = [];

        this.prepareNoChunksFormData(noChunkKeys, featureSet, formDataNoChunks);
        await this.startUploadNoChunksFormData(
          formDataNoChunks,
          featureSet,
          uploaded
        );
        const formDataChunks: FormDataChunks = {};
        await this.prepareChunksFormData(
          chunkKeys,
          featureSet,
          formDataChunks,
          uploaded
        );
        const formDataKeys = Object.keys(formDataChunks);
        await this.starUploadChunksFormData(
          formDataKeys,
          featureSet,
          formDataChunks
        );

        const cleanOperationsOfDataset = () => {
          return new Promise((resolve, reject) => {
            this.forceClean(featureSet.feature_set_id);
            resolve('success');
          });
        };

        const fetchFeatureSetStatusMutation = () => {
          return new Promise((resolve, reject) => {
            this.refreshFeatureSetList();
            resolve('success');
          });
        };

        this.pushUploadQueue({
          feature_set_id: '-1',
          project_id: '-1',
          requestAsync: cleanOperationsOfDataset,
          action: '',
        });

        this.pushUploadQueue({
          feature_set_id: '-1',
          project_id: '-1',
          requestAsync: fetchFeatureSetStatusMutation,
          action: '',
        });
      },

      forceClean(feature_set_id: string) {
        this.platformFeatureSetFileContainer[feature_set_id] = {
          fileChunks: {},
          fileNoChunks: {},
        };
        this.setCurProcessDatasetIds(
          this.platformCurrentProcessId.filter((id) => id != feature_set_id)
        );

        this.platformJumpRequestId = this.platformJumpRequestId.filter(
          (id) => id != feature_set_id
        );

        this.cleanQueueOfFeatureSet(feature_set_id);
        this.platformUploadIdMapper[feature_set_id] = {};
      },
      async starUploadChunksFormData(
        formDataKeys: string[],
        featureSet: CurrentFeatureSet,
        formDataChunks: FormDataChunks,
        uploaded?: Record<string, Record<string, string[]>>
      ) {
        const count = formDataKeys.length;
        let index = 0;
        const { feature_set_id, project_id } = featureSet;
        return new Promise((resolve, reject) => {
          if (!formDataKeys.length) resolve('');
          formDataKeys.map(async (key) => {
            try {
              const urls = this.platformUploadUrlsMapper[feature_set_id][key];
              let isAddImportingStatusChangeFunc = false;
              let isAddUploadingStatusChange = false;
              formDataChunks[key].map((formDataChunk, index) => {
                const FileChunkItem = formDataChunk.blob;
                const UploadFileQueueItem = () => {
                  // 测试数据集断点续传
                  // if (index > 12) return Promise.reject('');
                  return authedApi.request({
                    url: urls[formDataChunk.index!],
                    method: 'PUT',
                    data: FileChunkItem,
                    headers: { 'Content-Type': 'application/octet-stream' },
                    onUploadProgress: OnFileProgress(
                      this.platformFeatureSetFileContainer[feature_set_id]
                        .fileChunks[key][formDataChunk.index as number]
                    ),
                  });
                };

                const MergeFileQueueItem = () => {
                  return mergeChunks({
                    upload_id: this.platformUploadIdMapper[feature_set_id][key],
                    project_id,
                    feature_set_id,
                  });
                };

                const UpdateSuccessItem = () => {
                  return updateStatus({
                    project_id,
                    feature_set_id,
                    upload_id: this.platformUploadIdMapper[feature_set_id][key],
                  });
                };

                const importQueueItem = () => {
                  return importFile({
                    project_id,
                    feature_set_id,
                    data: {
                      filename: key,
                    },
                  });
                };

                const UpdateImporting = () => {
                  return updateImporting({
                    project_id,
                    feature_set_id,
                  });
                };

                const fetchDatasetStatusMutation = () => {
                  return new Promise((resolve, reject) => {
                    this.refreshFeatureSetList();
                    resolve('success');
                  });
                };

                if (formDataChunk.action == 'merge') {
                  if (uploaded) {
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: UpdateImporting,
                      action: '',
                    });
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: () => this.refreshFeatureSetList(),
                      action: '',
                    });
                  }
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadFeatureSet,
                    requestAsync: MergeFileQueueItem,
                    action: 'merge',
                    id: Number(formDataChunk.id),
                  });
                } else if (formDataChunk.action == 'import') {
                  if (uploaded) {
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: UpdateImporting,
                      action: '',
                    });
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: () => this.refreshFeatureSetList(),
                      action: '',
                    });
                  }
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadFeatureSet,
                    requestAsync: importQueueItem,
                    action: 'import',
                    id: Number(formDataChunk.id),
                  });
                } else if (formDataChunk.action == 'upload') {
                  if (uploaded && !isAddUploadingStatusChange) {
                    isAddUploadingStatusChange = true;
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: UpdateImporting,
                      action: '',
                    });
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: () => this.refreshFeatureSetList(),
                      action: '',
                    });
                  }
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadFeatureSet,
                    requestAsync: UploadFileQueueItem,
                    action: 'upload',
                    id: Number(formDataChunk.id),
                  });
                  this.platformRequestChunkSignal =
                    !this.platformRequestChunkSignal;
                } else if (formDataChunk.action == 'upload_successfully') {
                  this.pushUploadQueue({
                    ...this.platformCurrentUploadFeatureSet,
                    requestAsync: UpdateSuccessItem,
                    action: 'upload_successfully',
                    id: Number(formDataChunk.id),
                  });

                  if (uploaded) {
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: () => this.refreshFeatureSetList(),
                      action: '',
                    });
                  }

                  if (!isAddImportingStatusChangeFunc) {
                    this.pushUploadQueue({
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: fetchDatasetStatusMutation,
                      action: '',
                    });
                    isAddImportingStatusChangeFunc = true;
                  }
                }
              });
              index++;
              this.platformRequestChunkSignal =
                !this.platformRequestChunkSignal;

              if (index === count) {
                resolve('success');
              }
            } catch (e) {
              // location.reload();
              this.platformDeleteFeatureSetId.push(Number(feature_set_id));
              this.forceClean(feature_set_id);
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshFeatureSetList(),
              ]);
            }
          });
        });
      },
      prepareChunksFormData(
        chunkKeys: string[],
        featureSet: CurrentFeatureSet,
        formDataChunks: FormDataChunks,
        uploaded?: Record<string, Record<string, string[]>>
      ) {
        if (!chunkKeys.length) return;
        const count = chunkKeys.length;
        let i = 0;
        return new Promise((resolve, reject) => {
          const { feature_set_id, project_id } = featureSet;
          /* 后上传大文件切片 */
          chunkKeys.map(async (key) => {
            try {
              const fileResponse = await getFileId({
                project_id,
                feature_set_id,
                upload_id: this.platformUploadIdMapper[feature_set_id][key],
              });
              const fileInfo = fileResponse.data;
              const id = fileInfo.id;
              const item_error_status = fileInfo.error_status;
              const item_progress = fileInfo.progress;
              const item_status = fileInfo.status;
              // debugger;
              this.platformFeatureSetFileContainer[feature_set_id].fileChunks[
                key
              ].map(async (fileChunk) => {
                const { hash, chunk, index, filename } = fileChunk;
                if (
                  uploaded &&
                  uploaded[feature_set_id][key]?.includes(String(index))
                )
                  return;
                const formData = new FormData();
                formData.append('file', chunk!);
                formData.append('hash', hash);
                formData.append('filename', filename);
                formDataChunks[key] = formDataChunks[key] || [];
                formDataChunks[key].push({
                  formData: formData,
                  blob: chunk!,
                  index: index,
                  key: key,
                  action: 'upload',
                  id: String(id),
                });
              });

              if (uploaded) {
                // 续传 v3.0
                // debugger;
                if (item_error_status) {
                  if (item_error_status == 'upload') {
                    formDataChunks[key].push({
                      key: key,
                      action: 'upload_successfully',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'merge',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'import',
                      id: String(id),
                    });
                  } else if (item_error_status == 'upload_successfully') {
                    formDataChunks[key] = [];
                    formDataChunks[key].push({
                      key: key,
                      action: 'upload_successfully',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'merge',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'import',
                      id: String(id),
                    });
                  } else if (item_error_status == 'merge') {
                    formDataChunks[key] = [];
                    formDataChunks[key].push({
                      key: key,
                      action: 'merge',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'import',
                      id: String(id),
                    });
                  } else if (item_error_status == 'import') {
                    formDataChunks[key] = [];
                    formDataChunks[key].push({
                      key: key,
                      action: 'import',
                      id: String(id),
                    });
                  } else {
                    formDataChunks[key] = [];
                  }
                } else {
                  if (item_status == 'success' || item_progress >= 100) {
                    formDataChunks[key] = [];
                  } else {
                    formDataChunks[key].push({
                      key: key,
                      action: 'upload_successfully',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'merge',
                      id: String(id),
                    });
                    formDataChunks[key].push({
                      key: key,
                      action: 'import',
                      id: String(id),
                    });
                  }
                }
                i++;
                if (count == i) {
                  resolve('success');
                }
              } else {
                formDataChunks[key].push({
                  key: key,
                  action: 'upload_successfully',
                  id: String(id),
                });
                formDataChunks[key].push({
                  key: key,
                  action: 'merge',
                  id: String(id),
                });
                formDataChunks[key].push({
                  key: key,
                  action: 'import',
                  id: String(id),
                });
                i++;
                if (count == i) {
                  resolve('success');
                }
              }
            } catch (e) {
              this.platformDeleteFeatureSetId.push(Number(feature_set_id));
              location.reload();
              this.forceClean(String(feature_set_id));
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshFeatureSetList(),
              ]);
            }
          });
        });
      },
      prepareNoChunksFormData(
        noChunkKeys: string[],
        featureSet: CurrentFeatureSet,
        fileNoChunk: FormDataNoChunks[]
      ) {
        if (!noChunkKeys.length) return;
        noChunkKeys.map(async (key) => {
          const blobFile =
            this.platformFeatureSetFileContainer[featureSet.feature_set_id]
              .fileNoChunks[key][0].file;
          fileNoChunk.push({ formData: blobFile, key });
        });
      },

      async startUploadNoChunksFormData(
        noChunks: FormDataNoChunks[],
        featureSet: CurrentFeatureSet,
        uploaded?: Record<string, Record<string, string[]>>
      ) {
        let index = 0;
        const count = noChunks.length;
        const { project_id, feature_set_id } = featureSet;
        return new Promise((resolve, reject) => {
          if (!noChunks.length) resolve('success');
          noChunks.map(async ({ formData, key }) => {
            try {
              const noChunksBlob = formData;
              const fileResponse = await getFileId({
                project_id,
                feature_set_id,
                upload_id: this.platformUploadIdMapper[feature_set_id][key],
              });
              const fileInfo = fileResponse.data;
              const id = fileInfo.id;
              const item_error_status = fileInfo.error_status;
              const item_progress = fileInfo.progress;
              const item_status = fileInfo.status;
              const url = this.platformUploadUrlsMapper[feature_set_id][key][0];
              const UploadFileQueueItem = () => {
                // 测试数据集断点续传
                // return Promise.reject('111');
                return authedApi.request({
                  url,
                  method: 'PUT',
                  data: noChunksBlob,
                  headers: { 'Content-Type': 'application/octet-stream' },
                  onUploadProgress: OnFileProgress(
                    this.platformFeatureSetFileContainer[feature_set_id]
                      .fileNoChunks[key][0]
                  ),
                });
              };

              const importQueueItem = () => {
                return importFile({
                  project_id,
                  feature_set_id,
                  data: {
                    filename: key,
                  },
                });
              };

              const MergeFileQueueItem = () => {
                // return Promise.reject('1111');
                return mergeChunks({
                  upload_id: this.platformUploadIdMapper[feature_set_id][key],
                  project_id,
                  feature_set_id,
                });
              };

              const UpdateSuccessItem = () => {
                return updateStatus({
                  project_id,
                  feature_set_id,
                  upload_id: this.platformUploadIdMapper[feature_set_id][key],
                });
              };
              const addNoChunksQueue = () => {
                this.pushUploadQueue({
                  action: 'upload',
                  id,
                  ...this.platformCurrentUploadFeatureSet,
                  requestAsync: UploadFileQueueItem,
                });
                this.pushUploadQueue({
                  id: id,
                  action: 'upload_successfully',
                  ...this.platformCurrentUploadFeatureSet,
                  requestAsync: UpdateSuccessItem,
                });
                this.pushUploadQueue({
                  id: id,
                  action: 'merge',
                  ...this.platformCurrentUploadFeatureSet,
                  requestAsync: MergeFileQueueItem,
                });
                this.pushUploadQueue({
                  id: id,
                  action: 'import',
                  ...this.platformCurrentUploadFeatureSet,
                  requestAsync: importQueueItem,
                });
              };
              if (uploaded) {
                // 续传 v3.0
                // debugger;
                if (item_error_status) {
                  if (item_error_status == 'upload') {
                    addNoChunksQueue();
                  } else if (item_error_status == 'upload_successfully') {
                    this.pushUploadQueue({
                      id: id,
                      action: 'upload_successfully',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: UpdateSuccessItem,
                    });
                    this.pushUploadQueue({
                      id: id,
                      action: 'merge',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: MergeFileQueueItem,
                    });
                    this.pushUploadQueue({
                      id: id,
                      action: 'import',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: importQueueItem,
                    });
                  } else if (item_error_status == 'merge') {
                    this.pushUploadQueue({
                      id: id,
                      action: 'merge',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: MergeFileQueueItem,
                    });
                    this.pushUploadQueue({
                      id: id,
                      action: 'import',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: importQueueItem,
                    });
                  } else if (item_error_status == 'import') {
                    this.pushUploadQueue({
                      id: id,
                      action: 'import',
                      ...this.platformCurrentUploadFeatureSet,
                      requestAsync: importQueueItem,
                    });
                  } else {
                  }
                } else {
                  if (item_progress >= 100 || item_status == 'success') {
                  } else {
                    addNoChunksQueue();
                  }
                }
              } else {
                addNoChunksQueue();
              }
              index++;
              this.platformRequestChunkSignal =
                !this.platformRequestChunkSignal;
              if (index == count) {
                this.platformRequestSignal = !this.platformRequestSignal;
                resolve('success');
              }
            } catch (e) {
              this.platformDeleteFeatureSetId.push(Number(feature_set_id));
              this.forceClean(feature_set_id);
              location.reload();
              await Promise.all([
                this.initPlatformUploadList(),
                this.refreshFeatureSetList(),
              ]);
            }
          });
        });
      },
      async startScheduler() {
        if (
          this.platformUploadCount > this.platformMaxUploadRequestNum ||
          !this.platformUploadQueue.length
        )
          return;

        const uploadRequest = this.platformUploadQueue.shift();

        if (uploadRequest) {
          const action = uploadRequest.action;
          uploadRequest.requestAsync().then(
            () => this.platformUploadCount--,
            async () => {
              this.platformJumpRequestId.push(uploadRequest.feature_set_id!);
              try {
                if (action) {
                  if (uploadRequest.id) {
                    await updateItemStatus({
                      feature_set_id: uploadRequest.feature_set_id,
                      project_id: uploadRequest.project_id!,
                      status: action,
                      id: uploadRequest.id!,
                    });
                    await uploadErrorQueueItem({
                      feature_set_id: uploadRequest.feature_set_id!,
                      project_id: uploadRequest.project_id!,
                      action,
                    });
                  } else {
                    await uploadErrorQueueItem({
                      project_id: uploadRequest.project_id!,
                      feature_set_id: uploadRequest.feature_set_id,
                      action,
                    });
                  }

                  this.closeUploadModal();
                  this.forceClean(String(uploadRequest.feature_set_id));
                  this.platformUploadCount--;
                  ElMessage.error('上传发生错误，请继续上传');
                }
                await Promise.all([
                  this.initPlatformUploadList(),
                  this.refreshFeatureSetList(),
                ]);
              } catch (e: any) {
                this.platformFailureFeatureSetId.push(
                  uploadRequest?.feature_set_id
                );
                location.reload();
                this.forceClean(String(uploadRequest.feature_set_id));
                await Promise.all([
                  this.initPlatformUploadList(),
                  this.refreshFeatureSetList(),
                ]);
                this.platformUploadCount--;
              }
            }
          );
          this.platformRequestSignal = !this.platformRequestSignal;
          this.platformUploadCount++;
        }
      },
      cleanQueueOfFeatureSet(id: string) {
        this.platformUploadQueue = this.platformUploadQueue.filter(
          (q) => q.feature_set_id != id
        );
      },
    },

    persist: {
      enabled: true,
      strategies: [
        {
          storage: localStorage,
          paths: ['platformFailureDatasetId', 'platformCurrentProcessId'],
          key: 'platformFeatureSetUploadErrorQueue',
        },
        {
          storage: localStorage,
          paths: ['platformDeleteFeatureSetId'],
          key: 'platformUploadFDeleteQueue',
        },
      ],
    },
  }
);

type FileRowChuck = { file: Blob }[];

interface FormDataChunk {
  formData?: FormData;
  blob?: Blob;
  id: string;
  index?: number;
  key: string;
  action:
    | 'merge'
    | 'upload'
    | 'import'
    | 'upload_successfully'
    | 'clean_chunks';
}

type FormDataChunks = Record<string, FormDataChunk[]>;

interface FormDataNoChunks {
  formData: File;
  key: string;
}

export interface FileChunk {
  chunk?: Blob;
  hash: string;
  index: number;
  size: number;
  filename: string;
  percentage: number;
  rowSize: number;
  rowName: string;
}

export interface FileNoChunk {
  file: File;
  percentage: number;
  size: number;
  filename: string;
}

export interface fileChunks {
  dataset_id: number;
  version_id: number;
  chunks: Record<string, FileChunk[]>;
}

export interface FileContainer {
  fileChunks: Record<string, FileChunk[]>;
  fileNoChunks: Record<string, FileNoChunk[]>;
}

export interface CurrentDataset {
  id: number;
  title: string;
  version_id: number;
  project_id: string;
  version_title: string;
}

export interface UploadFeatureSetList {
  id: number;
  identifier: string;
  total_size: number;
  progress: number;
  feature_set_id: number;
  feature_set_title: string;
  status: string;
  row_name: string;
  create_time: string;
  upload_id: string;
}

export interface PlatformUploadUserFile extends UploadUserFile {
  feature_set_id: string;
}

export interface platformUploadQueue {
  feature_set_id: string;
  project_id: string;
  id?: number;
  action: string;
  requestAsync: () => Promise<any>;
}
